﻿using BanZuiCloudControlAgent.Extensions.QQ;
using BanZuiCloudControlAgent.Utils.Common;
using BanZuiCloudControlAgent.Utils.Logging;
using FlaUI.Core.AutomationElements;
using FlaUI.Core.Conditions;
using FlaUI.Core.Definitions;
using FlaUI.Core.Exceptions;
using FlaUI.UIA3;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace BanZuiCloudControlAgent.Automation
{
    /// <summary>
    /// QQ自动化操作类，封装QQ相关的所有自动化操作
    /// </summary>
    public class QQAutomation
    {
        private static readonly Logger _logger = LogManager.GetLogger(nameof(QQAutomation));
        private readonly UIA3Automation _automation;

        /// <summary>
        /// 构造函数
        /// </summary>
        public QQAutomation()
        {
            _automation = new UIA3Automation();
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            _automation?.Dispose();
        }

        #region 窗口查找

        /// <summary>
        /// 获取QQ主窗口
        /// </summary>
        /// <param name="processId">QQ进程ID，为0时查找所有QQ主窗口</param>
        /// <returns>QQ主窗口的AutomationElement</returns>
        public AutomationElement GetQQMainWindow(int processId = 0)
        {
            try
            {
                List<IntPtr> matchingWindows = new List<IntPtr>();

                if (processId > 0)
                {
                    // 根据进程ID查找窗口
                    var processWindows = Win32Api.FindWindowsByProcessId(processId, false);

                    // 筛选出符合条件的窗口
                    foreach (var hWnd in processWindows)
                    {
                        string className = Win32Api.GetWindowClassName(hWnd);
                        if (className == QQConstants.MainWindowClassName)
                        {
                            string title = Win32Api.GetWindowTitle(hWnd);
                            if (string.Equals(title, QQConstants.MainWindowTitle, StringComparison.OrdinalIgnoreCase))
                            {
                                matchingWindows.Add(hWnd);
                            }
                        }
                    }
                }
                else
                {
                    // 直接查找所有QQ主窗口
                    var windows = Win32Api.FindWindowsByClassName(QQConstants.MainWindowClassName, true, false);
                    foreach (var hWnd in windows)
                    {
                        string title = Win32Api.GetWindowTitle(hWnd);
                        if (string.Equals(title, QQConstants.MainWindowTitle, StringComparison.OrdinalIgnoreCase))
                        {
                            matchingWindows.Add(hWnd);
                        }
                    }
                }

                if (matchingWindows.Count <= 0)
                {
                    _logger.Error("未找到QQ主窗口");
                    return null;
                }

                // 转换为AutomationElement
                foreach (var handle in matchingWindows)
                {
                    AutomationElement mainWindow = _automation.FromHandle(handle);
                    if (mainWindow != null)
                    {
                        return mainWindow;
                    }
                }

                _logger.Error("无法将QQ窗口句柄转换为AutomationElement");
                return null;
            }
            catch (Exception ex)
            {
                _logger.Error($"获取QQ主窗口失败: {ex.Message}");
                return null;
            }
        }

        /// <summary>
        /// 获取QQ登录窗口
        /// </summary>
        /// <returns>QQ登录窗口的AutomationElement</returns>
        public AutomationElement GetLoginWindow()
        {
            try
            {
                // 查找所有QQ登录窗口
                var windows = Win32Api.FindWindowsByTitle(QQConstants.LoginWindowTitle);

                if (windows.Count <= 0)
                {
                    _logger.Error("未找到QQ登录窗口");
                    return null;
                }

                // 转换为AutomationElement
                foreach (var handle in windows)
                {
                    AutomationElement loginWindow = _automation.FromHandle(handle);
                    if (loginWindow != null)
                    {
                        return loginWindow;
                    }
                }

                _logger.Error("无法将QQ登录窗口句柄转换为AutomationElement");
                return null;
            }
            catch (Exception ex)
            {
                _logger.Error($"获取QQ登录窗口失败: {ex.Message}");
                return null;
            }
        }

        /// <summary>
        /// 获取QQ群聊窗口
        /// </summary>
        /// <param name="groupName">群名称，为空时返回第一个找到的群聊窗口</param>
        /// <param name="processId">QQ进程ID，为0时查找所有QQ进程的群聊窗口</param>
        /// <returns>群聊窗口的AutomationElement</returns>
        public AutomationElement GetGroupChatWindow(string groupName = null, int processId = 0)
        {
            try
            {
                List<IntPtr> windows = new List<IntPtr>();
                
                if (processId > 0)
                {
                    // 如果指定了进程ID，只查找该进程的窗口
                    windows = Win32Api.FindWindowsByProcessId(processId, true);
                    // 筛选出群聊窗口类名的窗口
                    windows = windows.FindAll(hWnd => 
                        Win32Api.GetWindowClassName(hWnd) == QQConstants.GroupChatWindowClassName);
                }
                else
                {
                    // 查找所有QQ群聊窗口
                    windows = Win32Api.FindWindowsByClassName(QQConstants.GroupChatWindowClassName, true, true);
                }

                if (windows.Count <= 0)
                {
                    if (processId > 0)
                        _logger.Error($"未找到进程ID为{processId}的QQ群聊窗口");
                    else
                        _logger.Error("未找到任何QQ群聊窗口");
                    return null;
                }

                // 遍历所有窗口，查找群聊窗口
                foreach (var handle in windows)
                {
                    // 将窗口句柄转换为AutomationElement
                    AutomationElement window = _automation.FromHandle(handle);
                    if (window == null)
                    {
                        continue;
                    }

                    // 查找窗口中的QQ电话按钮，这是群聊窗口的特征
                    var buttons = FindButtons(window, QQConstants.QQPhoneButtonTitle);
                    bool isGroupChatWindow = false;

                    foreach (var button in buttons)
                    {
                        if (button.Name == QQConstants.QQPhoneButtonTitle)
                        {
                            isGroupChatWindow = true;
                            break;
                        }
                    }

                    if (isGroupChatWindow)
                    {
                        string title = Win32Api.GetWindowTitle(handle);
                        int windowProcessId = Win32Api.GetWindowProcessId(handle);
                        
                        // 如果指定了进程ID，确认窗口属于该进程
                        if (processId > 0 && windowProcessId != processId)
                        {
                            continue;
                        }

                        // 如果指定了群名称，则进一步匹配
                        if (string.IsNullOrEmpty(groupName) || (title != null && title.Contains(groupName)))
                        {
                            _logger.Info($"找到群聊窗口: {title}, 进程ID: {windowProcessId}");
                            return window;
                        }
                    }
                }

                if (processId > 0)
                {
                    if (string.IsNullOrEmpty(groupName))
                        _logger.Error($"未找到进程ID为{processId}的QQ的群聊窗口");
                    else
                        _logger.Error($"未找到进程ID为{processId}的QQ的名为'{groupName}'的群聊窗口");
                }
                else
                {
                    if (string.IsNullOrEmpty(groupName))
                        _logger.Error("未找到任何群聊窗口");
                    else
                        _logger.Error($"未找到名为'{groupName}'的群聊窗口");
                }
                return null;
            }
            catch (Exception ex)
            {
                _logger.Error($"获取QQ群聊窗口失败: {ex.Message}");
                return null;
            }
        }

        /// <summary>
        /// 获取当前显示的QQ菜单窗口
        /// </summary>
        /// <returns>菜单窗口的AutomationElement</returns>
        public AutomationElement GetMenuWindow()
        {
            try
            {
                // 查找所有菜单窗口
                var menuWindows = Win32Api.FindWindowsByClassName(QQConstants.MenuWindowClassName, true, true);

                if (menuWindows.Count <= 0)
                {
                    _logger.Error("未找到任何菜单窗口");
                    return null;
                }

                // 菜单通常是最后打开的窗口，所以取最后一个
                var menuHandle = menuWindows[menuWindows.Count - 1];
                AutomationElement menuWindow = _automation.FromHandle(menuHandle);

                if (menuWindow == null)
                {
                    _logger.Error("无法将菜单窗口句柄转换为AutomationElement");
                    return null;
                }

                return menuWindow;
            }
            catch (Exception ex)
            {
                _logger.Error($"获取QQ菜单窗口失败: {ex.Message}");
                return null;
            }
        }

        #endregion

        #region UI元素操作

        /// <summary>
        /// 查找菜单项
        /// </summary>
        /// <param name="menuWindow">菜单窗口</param>
        /// <param name="menuItemName">菜单项名称</param>
        /// <returns>菜单项元素</returns>
        public AutomationElement FindMenuItem(AutomationElement menuWindow, string menuItemName)
        {
            try
            {
                if (menuWindow == null)
                {
                    _logger.Error("菜单窗口为空");
                    return null;
                }

                // 查找所有菜单项
                var menuItems = menuWindow.FindAllChildren();
                var menuItem = menuItems.FirstOrDefault(item => item.Name == menuItemName);

                if (menuItem == null)
                {
                    _logger.Error($"未找到名为'{menuItemName}'的菜单项");
                    return null;
                }

                return menuItem;
            }
            catch (Exception ex)
            {
                _logger.Error($"查找菜单项失败: {ex.Message}");
                return null;
            }
        }

        /// <summary>
        /// 点击菜单项
        /// </summary>
        /// <param name="menuWindow">菜单窗口</param>
        /// <param name="menuItemName">菜单项名称</param>
        /// <returns>操作是否成功</returns>
        public bool ClickMenuItem(AutomationElement menuWindow, string menuItemName)
        {
            try
            {
                var menuItem = FindMenuItem(menuWindow, menuItemName);
                if (menuItem == null)
                {
                    return false;
                }

                // 点击菜单项
                menuItem.Click();
                _logger.Info($"已点击菜单项: {menuItemName}");
                return true;
            }
            catch (Exception ex)
            {
                _logger.Error($"点击菜单项失败: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 获取菜单项是否被选中
        /// </summary>
        /// <param name="menuWindow">菜单窗口</param>
        /// <param name="menuItemName">菜单项名称</param>
        /// <returns>菜单项是否被选中，null表示无法确定</returns>
        public bool? GetMenuItemChecked(AutomationElement menuWindow, string menuItemName)
        {
            try
            {
                var menuItem = FindMenuItem(menuWindow, menuItemName);
                if (menuItem == null)
                {
                    return null;
                }

                // 尝试通过Toggle模式获取状态
                if (menuItem.Patterns.Toggle?.IsSupported == true)
                {
                    bool isChecked = menuItem.Patterns.Toggle.Pattern.ToggleState.Value == ToggleState.On;
                    _logger.Info($"菜单项 {menuItemName} 选中状态: {isChecked}");
                    return isChecked;
                }
                // 尝试通过LegacyIAccessible模式获取状态
                else if (menuItem.Patterns.LegacyIAccessible?.IsSupported == true)
                {
                    var state = menuItem.Patterns.LegacyIAccessible.Pattern.State;
                    // 通常状态值中的某些位表示选中状态，具体需要根据实际情况调整
                    bool isChecked = (int)state.Value != 0;
                    _logger.Info($"菜单项 {menuItemName} 可能的选中状态: {isChecked}");
                    return isChecked;
                }
                else
                {
                    _logger.Error($"无法获取菜单项 {menuItemName} 的选中状态");
                    return null;
                }
            }
            catch (Exception ex)
            {
                _logger.Error($"获取菜单项选中状态失败: {ex.Message}");
                return null;
            }
        }

        /// <summary>
        /// 查找按钮
        /// </summary>
        /// <param name="parentWindow">父窗口</param>
        /// <param name="buttonName">按钮名称，为空时返回所有按钮</param>
        /// <returns>按钮元素或按钮元素集合</returns>
        public AutomationElement[] FindButtons(AutomationElement parentWindow, string buttonName = null)
        {
            try
            {
                if (parentWindow == null)
                {
                    _logger.Error("父窗口为空");
                    return new AutomationElement[0];
                }

                // 查找所有按钮
                var buttons = parentWindow.FindAllDescendants(cf => cf.ByControlType(ControlType.Button));

                if (string.IsNullOrEmpty(buttonName))
                {
                    return buttons;
                }

                // 按名称筛选
                return buttons.Where(button => button.Name == buttonName).ToArray();
            }
            catch (Exception ex)
            {
                _logger.Error($"查找按钮失败: {ex.Message}");
                return new AutomationElement[0];
            }
        }

        #endregion

        #region 业务操作
        /// <summary>
        /// 从UI界面来判断QQ是否在线
        /// </summary>
        /// <param name="targetProcessId">QQ进程ID</param>
        /// <returns>是否在线</returns>
        //public  bool IsQQOnlineFromUI(int targetProcessId) {
        //    AutomationElement qqMainWindow = GetQQMainWindowWin32(targetProcessId);
        //    if (qqMainWindow == null) {
        //        _logger.Error("未找到QQ主窗口");
        //        return false;
        //    }
        //    // 查找所有按钮
        //    var allButtons = qqMainWindow.FindAllDescendants(cf => cf.ByControlType(FlaUI.Core.Definitions.ControlType.Button));

        //    // 如果找到按钮
        //    if (allButtons != null && allButtons.Length > 0) {
        //        _logger.Info($"共找到 {allButtons.Length} 个按钮控件:\r\n");

        //        // 遍历所有按钮并输出HelpText
        //        for (int i = 0; i < allButtons.Length; i++) {
        //            string desc = GetElementDescription(allButtons[i]);
        //            // 只要出现 "在线状态菜单" 就是在线
        //            if (desc.Contains(QQConstants.OnlineStatusMenuDescription)) {
        //                _logger.Info("QQ在线");
        //                return true;
        //            }
        //        }

        //        // 如果遍历完所有按钮都没找到"在线状态菜单"，则认为是离线状态
        //        _logger.Info("QQ离线");
        //        return false;
        //    }

        //    _logger.Error("未找到任何按钮控件");
        //    return false;
        //}
        /// <summary>
        /// 判断QQ是否在线
        /// </summary>
        /// <param name="processId">QQ进程ID，为0时查找所有QQ窗口</param>
        /// <returns>QQ是否在线</returns>
        public bool IsQQOnline(int processId = 0)
        {
            try
            {
                // 获取QQ主窗口
                AutomationElement mainWindow = GetQQMainWindow(processId);
                if (mainWindow == null)
                {
                    return false;
                }

                // 查找所有按钮
                var buttons = FindButtons(mainWindow);

                // 遍历所有按钮，查找在线状态菜单
                foreach (var button in buttons)
                {
                    string desc = GetElementDescription(button);
                    if (desc.Contains(QQConstants.OnlineStatusMenuDescription))
                    {
                        _logger.Info("QQ在线");
                        return true;
                    }
                }

                _logger.Info("QQ离线");
                return false;
            }
            catch (Exception ex)
            {
                _logger.Error($"判断QQ在线状态失败: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 检查群消息是否被屏蔽
        /// </summary>
        /// <param name="processId">QQ进程ID</param>
        /// <returns>群消息是否被屏蔽，null表示无法确定</returns>
        public bool? IsGroupMessageBlocked(int processId)
        {
            try
            {
                // 获取QQ主窗口
                AutomationElement mainWindow = GetQQMainWindow(processId);
                if (mainWindow == null)
                {
                    return null;
                }

                // 等待操作
                Thread.Sleep(QQConstants.OperationWaitTime);

                // 1. 记录初始菜单窗口
                var initialMenuWindows = Win32Api.FindWindowsByClassName(QQConstants.MenuWindowClassName);
                var initialWindowHandles = new HashSet<IntPtr>(initialMenuWindows);

                // 2. 查找群消息设置菜单项
                var menuItems = mainWindow.FindAllChildren();
                var groupMessageSettings = menuItems.FirstOrDefault(item =>
                    item.Name == QQConstants.GroupMessageSettingsMenuItemName);

                if (groupMessageSettings == null)
                {
                    _logger.Error($"未找到'{QQConstants.GroupMessageSettingsMenuItemName}'菜单项");
                    return null;
                }

                // 3. 点击群消息设置菜单项
                groupMessageSettings.Click();
                _logger.Info($"已点击'{QQConstants.GroupMessageSettingsMenuItemName}'菜单项");

                // 4. 等待二级菜单窗口出现
                Thread.Sleep(QQConstants.MenuWaitTime);

                // 5. 查找新出现的窗口
                var newMenuWindows = Win32Api.FindWindowsByClassName(QQConstants.MenuWindowClassName);
                var newWindows = newMenuWindows.Where(w => !initialWindowHandles.Contains(w)).ToList();

                if (newWindows.Count == 0)
                {
                    _logger.Error("未找到新的菜单窗口");
                    return null;
                }

                // 6. 使用第一个新窗口作为二级菜单窗口
                var secondMenuHandle = newWindows[0];
                var secondMenuWindow = _automation.FromHandle(secondMenuHandle);

                if (secondMenuWindow == null)
                {
                    _logger.Error("无法将窗口句柄转换为AutomationElement");
                    return null;
                }

                // 7. 查找屏蔽群消息菜单项
                var subMenuItems = secondMenuWindow.FindAllChildren();
                var blockGroupMessage = subMenuItems.FirstOrDefault(item =>
                    item.Name == QQConstants.BlockGroupMessageMenuItemName);

                if (blockGroupMessage == null)
                {
                    _logger.Error($"未找到'{QQConstants.BlockGroupMessageMenuItemName}'菜单项");
                    return null;
                }

                // 8. 获取菜单项是否被选中
                bool? isChecked = GetMenuItemChecked(secondMenuWindow, QQConstants.BlockGroupMessageMenuItemName);
                return isChecked;
            }
            catch (Exception ex)
            {
                _logger.Error($"检查群消息是否被屏蔽失败: {ex.Message}");
                return null;
            }
        }

        /// <summary>
        /// 设置是否屏蔽群消息
        /// </summary>
        /// <param name="processId">QQ进程ID</param>
        /// <param name="block">是否屏蔽</param> 
        /// <returns>操作是否成功</returns>
        public bool SetBlockGroupMessage(int processId,bool block)
        {
            try
            {
                // 先检查当前状态
                bool? currentState = IsGroupMessageBlocked(processId);

                // 如果当前状态与目标状态相同，或者无法确定当前状态，则不操作
                if (currentState == null)
                {
                    _logger.Error("无法确定当前群消息屏蔽状态");
                    return false;
                }

                if (currentState == block)
                {
                    _logger.Info($"群消息屏蔽状态已经是 {block}，无需操作");
                    return true;
                }

                // 重新打开菜单
                // 获取QQ主窗口
                AutomationElement mainWindow = GetQQMainWindow(processId);
                if (mainWindow == null)
                {
                    return false;
                }

                // 等待操作
                Thread.Sleep(QQConstants.OperationWaitTime);

                // 1. 记录初始菜单窗口
                var initialMenuWindows = Win32Api.FindWindowsByClassName(QQConstants.MenuWindowClassName);
                var initialWindowHandles = new HashSet<IntPtr>(initialMenuWindows);

                // 2. 查找群消息设置菜单项
                var menuItems = mainWindow.FindAllChildren();
                var groupMessageSettings = menuItems.FirstOrDefault(item =>
                    item.Name == QQConstants.GroupMessageSettingsMenuItemName);

                if (groupMessageSettings == null)
                {
                    _logger.Error($"未找到'{QQConstants.GroupMessageSettingsMenuItemName}'菜单项");
                    return false;
                }

                // 3. 点击群消息设置菜单项
                groupMessageSettings.Click();
                _logger.Info($"已点击'{QQConstants.GroupMessageSettingsMenuItemName}'菜单项");

                // 4. 等待二级菜单窗口出现
                Thread.Sleep(QQConstants.MenuWaitTime);

                // 5. 查找新出现的窗口
                var newMenuWindows = Win32Api.FindWindowsByClassName(QQConstants.MenuWindowClassName);
                var newWindows = newMenuWindows.Where(w => !initialWindowHandles.Contains(w)).ToList();

                if (newWindows.Count == 0)
                {
                    _logger.Error("未找到新的菜单窗口");
                    return false;
                }

                // 6. 使用第一个新窗口作为二级菜单窗口
                var secondMenuHandle = newWindows[0];
                var secondMenuWindow = _automation.FromHandle(secondMenuHandle);

                if (secondMenuWindow == null)
                {
                    _logger.Error("无法将窗口句柄转换为AutomationElement");
                    return false;
                }

                // 7. 点击屏蔽群消息菜单项
                bool clicked = ClickMenuItem(secondMenuWindow, QQConstants.BlockGroupMessageMenuItemName);
                if (!clicked)
                {
                    return false;
                }

                // 验证操作是否成功
                Thread.Sleep(QQConstants.OperationWaitTime);
                bool? newState = IsGroupMessageBlocked(processId);

                if (newState == null)
                {
                    _logger.Error("无法确定操作后群消息屏蔽状态");
                    return false;
                }

                if (newState != block)
                {
                    _logger.Error($"设置群消息屏蔽状态失败，当前状态为 {newState}，目标状态为 {block}");
                    return false;
                }

                _logger.Info($"成功设置群消息屏蔽状态为 {block}");
                return true;
            }
            catch (Exception ex)
            {
                _logger.Error($"设置群消息屏蔽状态失败: {ex.Message}");
                return false;
            }
        }

        #endregion

        #region 辅助方法

        /// <summary>
        /// 获取元素描述
        /// </summary>
        /// <param name="element">自动化元素</param>
        /// <returns>元素描述</returns>
        private string GetElementDescription(AutomationElement element)
        {
            try
            {
                // 使用LegacyIAccessible模式获取描述
                if (element.Patterns.LegacyIAccessible.IsSupported)
                {
                    var legacyPattern = element.Patterns.LegacyIAccessible.PatternOrDefault;
                    return legacyPattern?.Description ?? string.Empty;
                }
            }
            catch (Exception ex)
            {
                _logger.Error($"获取元素描述失败: {ex.Message}");
            }
            return string.Empty;
        }

        #endregion
    }
}